<?php
/**
 * AccessControl.class.php
 *
 * PHP version 5
 *
 * Copyright (c) 2006-2009, Code Coop SA
 * Copyright (c) 2009, Fredrik Larsen
 * Copyright (c) 2010, Leo Valen  http://www.valen.pro
 * All rights reserved.
 *
 * @author		Leo Valen <leo@valen.pro>
 * @author      Fredrik Larsen <f@code.coop>
 */
/**
 * Implementation of Hierarchical Role Based Access Control for TeamPlayers
 *
 * @version		1.0
 */
namespace TeamPlayers;
class AccessControl
{
	/**
	 * User name
	 *
	 * @var string
	 * @access public
	 */
	public $user;
	/**
	 * Real name
	 *
	 * @var string
	 * @access public
	 */
	public $name;
	/**
	 * email address
	 *
	 * @var string
	 * @access public
	 */
	public $email;
	/**
	 * Plaintext password
	 *
	 * @var string
	 * @access public
	 */
	public $plaintext;
	/**
	 * SHA1 hashed password
	 *
	 * @var string
	 * @access public
	 */
	public $password;	
	/**
	 * Session ID
	 *
	 * @var string
	 * @access public
	 */
	public $sessionId;
	/**
	 * Remote address
	 *
	 * @var string
	 * @access public
	 */
	public $address;
	/**
	 * True if the user is not a guest
	 *
	 * @var boolean
	 * @access public
	 */
	public $authenticated;
	/**
	 * True if login was successful
	 *
	 * @var boolean
	 * @access public
	 */
	public $authenticationSuccessful;
	/**
	 * True if login failed
	 *
	 * @var boolean
	 * @access public
	 */
	public $authenticationFailed;
	/**
	 * True if account has been blocked
	 *
	 * @var boolean
	 * @access public
	 */
	public $accountBlocked;
	/**
	 * True if the user has been logged out
	 *
	 * @var boolean
	 * @access public
	 */
	public $logout;
	/**
	 * Privileges array
	 *
	 * @var array
	 * @access protected
	 */
	protected $privilege;
	/**
	 * Whether privileges have been fetched
	 *
	 * @var boolean
	 * @access protected
	 */
	protected $didFetchPrivileges;
	/**
	 * Current site
	 *
	 * @var string
	 * @access protected
	 */
	protected $site;
	/**
	 * Roles array
	 *
	 * @var string
	 * @access protected
	 */
	protected $roles;
	/**
	 * Validates user and fetches user data
	 *
	 * @return		void
	 * @access		public
	 */
	function __construct()
	{
		$this->authenticated = false;
		$this->privilege = array();
		$this->address = $_SERVER['REMOTE_ADDR'];
		$this->site = "TeamPlayers.no";
	}
	/**
	* Attempts to authenticate the user from GET, POST or COOKIE data
	*
	* @return		void
	* @access		public
	*/
	public function authenticateFromUserInput()
	{
		/*
		 * Set sessionId to previous session if it exists
		 */
		$this->sessionId = $this->sessionIdFromCookie();
		/*
		 * Check if credentials were supplied by GET or POST
		 */
		if ( isset( $_GET['user'] ) && isset( $_GET['password'] ) )
		{
			$this->authenticate( $_GET['user'], $_GET['password'] );
		}
		else if ( isset( $_POST['user'] ) && isset( $_POST['password'] ) )
		{
			$this->authenticate( $_POST['user'], $_POST['password'] );
		}
		/*
		 * Check if there is already a session
		 */
		else if ( isset( $_COOKIE['sessionId'] ) )
		{
			$this->renew( $this->sessionIdFromCookie() );
		}
		else
		{
			$this->authenticate();
		}
	}
	/**
	 * Starts a session with the provided login details if valid
	 *
	 * @param		string $user		User name
	 * @param		string $password	password
	 * @param		bool $hashed		Whether the supplied password is hashed
	 * @param       bool $override      Whether to override password authentication
	 * @return		void
	 * @access		public
	 */
	public function authenticate( $user = 'guest', $password = "", $hash = false, $override = false )
	{
	    $this->user = "";
		/*
		 * Escape user address and hash password
		 */
		if ( $user != 'guest' )
		{
			$user = TeamPlayers::$db->real_escape_string( $user );
		}
		$sha1password = sha1( $password );
		if ( $user == 'guest' )
		{
			$this->user = "guest";
			$this->name = "Guest";
			$this->password = "";
			return true;
		}
		else
		{
			/*
		 	* Check if too many failed authentication attempts have already been made
		 	*/
			$timeframe		= 300;
			$maxAttempts	= 10;
			$attemptDelayThreshold = 3;
			$sql = "SELECT
						COUNT( `id` )
					FROM
						`AccessControlAuthenticationLog`
					WHERE
						`user` = '{$user}'
					AND
						`successful` = 0
					AND
						`time` > NOW() - INTERVAL {$timeframe} SECOND";
			if ( $result = TeamPlayers::$db->query( $sql ) )
			{
				$row = $result->fetch_row();
				$count = $row[0];
				if ( $count >= $maxAttempts )
				{
					$this->accountBlocked = true;
					$this->authenticate();
					return false;
				}
			}
			/*
			 * Attempt authenticating the user against the mysql user table
			 */
			if ( $override === true )
			{
			    $sql = "SELECT
			    			`user`, `name`, `email`, `password`
			    		FROM
			    			`AccessControlUser`
			    		WHERE
			    			( `user` = '{$user}' AND `status` = 'active' )";
			}
			else
			{
			    $sql = "SELECT
			    			`user`, `name`, `email`, `password`
			    		FROM
			    			`AccessControlUser`
			    		WHERE
			    			( `user` = '{$user}' AND `password` = '{$sha1password}' AND `status` = 'active' )";
			}
			if ( $result = TeamPlayers::$db->selectAssoc( $sql ) )
			{    
				$row = $result[0];
				$this->user = $row['user'];
				$this->name = $row['name'];
				$this->email = $row['email'];
				$this->password = $row['password'];
			}
			else
			{
				
			    /*
			     * Attempt authenticating against LDAP
			     */
			     
			    if ( $result = $this->ldapBind( $user, $password ) )
			    {
			        $this->user = $result['user'];
			        $this->name = $result['name'];
			        $this->email = $result['email'];
			        $this->password = $sha1password;
			        /*
			         * Save user data to mysql table
			         */
			        $sql = "REPLACE INTO
			                    `AccessControlUser`
			                SET
			                    `user` = '{$this->user}',
			                    `name` = '{$this->name}',
			                    `email` = '{$this->email}',
			                    `ldapUser` = 1,
			                    `status` = 'active'";
			        TeamPlayers::$db->query( $sql );
			    }
			}
			if ( ! empty( $this->user ) )
			{
				/*
				 * Authentication successful
				 */
				$this->authenticated = true;
				$this->authenticationSuccessful( $user );
			}
			else
			{
				/*
				 * Authentication failed
				 */
				if ( $count >= $attemptDelayThreshold )
				{
				    /*
				     * Wait for a few seconds if the login failed and the attempt count exceeds the threshold
				     */
				    if ( $count >= $attemptDelayThreshold )
				    {
				        sleep( ( $count - 3 ) * 3 );
				    }
				}
				$this->authenticationFailed( $user, $password );
				if ( isset( $_COOKIE['sessionId'] ) )
				{
					$this->renew( $this->sessionIdFromCookie() );
					return false;
				}
				else
				{
					$this->authenticate();
					return false;
				}
			}
			/*
			 * Remove the current session
			 */
			$this->removeSession();
			/*
			 * Store the session and perform maintenance
			 */
			$this->sessionId = TeamPlayers::uuid();
			$this->writeSession();
			$this->removeExpiredSessions();
			return true;
		}
	}
	/**
	* Terminates the current session
	*
	* @return		void
	* @access		public
	*/
	public function logout()
	{
    	setcookie( 'sessionId', 0, time() - 60 * 60 * 24 * 30, "/", $_SERVER['HTTP_HOST'] );
    	$this->logout = true;
    	$this->authenticated = false;
    	$this->authenticate();
	}
	/**
	 * Returns true if the currently authenticated user has the specified privilege
	 *
	 * @param		string $permission
	 * @param		string $class
	 * @param       string $object
	 * @param       string $user Defaults to the currently logged in user
	 * @param       bool $grant  Check if the user has the privilege to grant this permission
	 * @return		bool
	 * @access		public
	 */
	public function can( $permission, $class, $object = "", $user = "", $grant = false )
	{
		if ( empty( $user ) )
		{
		    $this->fetchPrivileges();
		    $privileges = $this->privilege;
		}
		else
		{
		    $privileges = $this->getPrivilegesForUser( $user );
		}
		$authorized = false;
		if ( $grant == false )
		{
    		/*
    		 * Check if the user has the specified privilege on all objects of a class
    		 */
    		if ( isset( $privileges[$class]['class'][$permission] ) && $privileges[$class]['class'][$permission] )
    		{
    		    $authorized |= true;
    		}
    		/*
    		 * Check if the user has the specified privilege on the specified object of a class
    		 */
    		if ( is_object( $object ) )
    		{
    		    $object = $object->getUuid();
    		}
    		if ( isset( $privileges[$class]['objects'][$object][$permission] ) && $privileges[$class]['objects'][$object][$permission] )
    		{
    		    $authorized |= true;
    		}
    	}
    	else
    	{
    	    /*
    	     * Check if the user has the permission to grant the specified privilege on all objects of a class
    	     */
    	    if ( isset( $privileges[$class]['class']['grant'][$permission] ) && $privileges[$class]['class']['grant'][$permission] )
    	    {
    	        $authorized |= true;
    	    }
    	    /*
    	     * Check if the user has the specified privilege on the specified object of a class
    	     */
    	    if ( is_object( $object ) )
    	    {
    	        $object = $object->getUuid();
    	    }
    	    if ( isset( $privileges[$class]['objects'][$object]['grant'][$permission] ) && $privileges[$class]['objects'][$object]['grant'][$permission] )
    	    {
    	        $authorized |= true;
    	    }
    	    /*
    	     * Users with the editPermissions privilege can grant any permission
    	     */
    	    if ( $this->allows( 'editPermissions' ) )
    	    {
    	        $authorized |= true;
    	    }
    	}
		return $authorized;
	}
	/**
	 * Returns true if the currently logged in user or a specified user has the specified role
	 *
	 * @param		string $role
	 * @param		string $user
	 * @return		bool
	 * @access		public
	 */
	public function hasRole( $role, $user = "" )
	{
	    if ( ! empty( $user ) )
	    {
	        $roles = array();
	        $privileges = $this->getPrivilegesForUser( $user, $roles );
	    }
	    else
	    {
	        $roles = array();
	        $privileges = $this->getPrivilegesForUser( $this->user, $roles );
	    }
	    $hasRole = false;
	    foreach ( $roles as $array )
	    {
	        if ( $array['role'] == $role )
	        {
	            $hasRole = true;
	            break;
	        }
	    }
	    return $hasRole;
	}
	/**
	 * Returns true if the currently logged in user has the privilege to grant the specified role
	 *
	 * @param		string $role
	 * @param		string $user
	 * @return		bool
	 * @access		public
	 */
	public function canAssignRole( $role, $user = "" )
	{
		if ( ! empty( $user ) )
		{
		    $roles = array();
		    $privileges = $this->getPrivilegesForUser( $user, $roles );
		}
		else
		{
		    $roles = $this->roles;
		    $privileges = $this->privilege;
		}
		$authorized = false;
		foreach ( $roles as $array )
		{
		    if ( $array['role'] == $role && $array['grant'] == true )
		    {
		        $authorized = true;
		        break;
		    }
		}
		if ( ! $authorized )
		{
		    /*
		     * Users with the editRoles privilege can grant any role
		     */
		    if ( isset( $privileges[__CLASS__]['class']['editRoles'] ) && $privileges[__CLASS__]['class']['editRoles'] )
		    {
		        $authorized = true;
		    }
		}
		return $authorized;
	}
	/**
	 * Returns an array of the currently logged in user's or a specified user's permissions
	 *
	 * @param       string $user   The user name
	 * @param       string $grant  Whether to only return permissions that the user can grant to other users and roles
	 * @return		array
	 * @access		public
	 */
	public function getPermissions( $user = '', $grant = false )
	{
	    $permissions = TeamPlayers::$ac->getPrivilegesForUser( $user );
	    $thePermissions = array();
	    if ( $grant )
	    {
    	    foreach ( $permissions as $class => $p )
    	    {
    	        if ( isset( $p['class']['grant'] ) && is_array( $p['class']['grant'] ) )
    	        {
    	            foreach ( $p['class']['grant'] as $permission )
    	            {
    	                $thePermissions[] = array(
    	                    'permission' => $permission,
    	                    'class' => $class,
    	                    'object' => '',
    	                    'grant' => true
    	                );
    	            }
    	        }
    	        if ( isset( $p['objects'] ) && is_array( $p['objects'] ) )
    	        {
    	            foreach ( $p['objects'] as $uuid => $object )
    	            {
    	                if ( isset( $object['grant'] ) )
    	                {
        	                foreach ( $object['grant'] as $permission )
        	                {
        	                    $thePermissions[] = array(
        	                        'permission' => $permission,
        	                        'class' => $class,
        	                        'object' => $uuid,
        	                        'grant' => true
        	                    );
        	                }
        	            }
    	            }
    	        }
    	    }
    	}
    	else
    	{
    	    foreach ( $permissions as $class => $p )
    	    {
    	        if ( isset( $p['class'] ) )
    	        {
    	            foreach ( $p['class'] as $key => $permission )
    	            {
    	                if ( $key != 'grant' )
    	                {
        	                $array = array(
        	                    'permission' => $permission,
        	                    'class' => $class,
        	                    'object' => ''
        	                );
        	                if ( isset( $p['class']['grant'][$permission] ) && $p['class']['grant'][$permission] == true )
        	                {
        	                    $array['grant'] = true;
        	                }
        	                else
        	                {
        	                    $array['grant'] = false;
        	                }
        	                $thePermissions[] = $array;
        	            }
    	            }
    	        }
    	        if ( isset( $p['objects'] ) && is_array( $p['objects'] ) )
    	        {
    	            foreach ( $p['objects'] as $uuid => $object )
    	            {
    	                unset( $key );
    	                foreach ( $object as $key => $permission )
    	                {
    	                    if ( $key != 'grant' )
    	                    {
        	                    $array = array(
        	                        'permission' => $permission,
        	                        'class' => $class,
        	                        'object' => $uuid
        	                    );
        	                    if ( isset( $object['grant'][$permission] ) && $object['grant'][$permission] == true )
        	                    {
        	                        $array['grant'] = true;
        	                    }
        	                    else
        	                    {
        	                        $array['grant'] = false;
        	                    }
        	                    $thePermissions[] = $array;
        	                }
    	                }
    	            }
    	        }
    	    }
    	}
	    unset( $p );
	    $permissionsString = "( ";
	    foreach ( $thePermissions as $p )
	    {
	        $permissionsString .= "'{$p['permission']}'" . ", ";
	    }
	    $permissionsString = rtrim( $permissionsString, ", " ) . " )";
	    /*
	     * Fetch permission descriptions
	     */
	    $sql = "SELECT
	                `permission`, `description`
	            FROM
	                `AccessControlPermission`
	            WHERE
	                `permission`
	            IN
	                {$permissionsString}";
	    $permissionNames = TeamPlayers::$db->selectAssoc( $sql );
	    $permissionNamesAssoc = array();
	    if ( ! empty( $permissionNames ) )
	    {
    	    foreach ( $permissionNames as $permissionName )
    	    {
    	        $permissionNamesAssoc[$permissionName['permission']] = $permissionName;
    	    }
    	}
	    foreach ( $thePermissions as & $p )
	    {
	        $p['description'] = $permissionNamesAssoc[$p['permission']]['description'];
	    }
	    /*
	     * Fetch object descriptions
	     */
	    $objects = 0;
	    unset( $p );
	    $objectsString = "( ";
	    foreach ( $thePermissions as $p )
	    {
	        if ( ! empty( $p['object'] ) )
	        {
	            $objectsString .= "'{$p['object']}'" . ", ";
	            $objects++;
	        }
	    }
	    $objectsString = rtrim( $objectsString, ", " ) . " )";
	    if ( $objects > 0 )
	    {
	        $sql = "SELECT
	                    `uuid`,
	                    `description` AS `objectDescription`
	                FROM
	                    `StoredObjects`
	                WHERE
	                    `uuid`
	                IN
	                    {$objectsString}";
	        $objectDescriptions = TeamPlayers::$db->selectAssoc( $sql );
	        $objectDescriptionsAssoc = array();
	        foreach ( $objectDescriptions as $objectDescription )
	        {
	            $objectDescriptionsAssoc[$objectDescription['uuid']] = $objectDescription['objectDescription'];
	        }
	    }
	    unset( $p );
	    foreach ( $thePermissions as & $p )
	    {
	        if ( ! empty( $p['object'] ) && isset( $objectDescriptionsAssoc[$p['object']] ) )
	        {
	            $p['objectDescription'] = $objectDescriptionsAssoc[$p['object']];
	        }
	        else
	        {
	            $p['objectDescription'] = "";
	        }
	    }
	    return $thePermissions;
	}
	/**
	 * Checks if the current user has the specified privilege and redirects to login page else
	 *
	 * @param		string $permission			the permission required
	 * @param		string $realm				realm reference
	 * @param		string $site				site reference
	 * @param		string $loginURI			URI to login page
	 * @return		void
	 * @access		public
	 */
	public function authorize( $permission, $realm, $site = "", $loginURI = "/login/" )
	{
		if ( ! $this->can( $permission, $realm, $site ) && $loginURI )
		{
			$redirect = TeamPlayers::$request_uri;
			@$_GET['redirect'] ? $location = $_GET['redirect'] : $location = "{$loginURI}?permission={$permission}&realm={$realm}&redirect={$redirect}";
			header( "Location: {$location}" );
		}
	}
	/**
	 * Writes the session to the database
	 *
	 * @return		void
	 * @access		protected
	 */
	protected function writeSession()
	{
		$sessionId = $this->sessionId;
		$user = $this->user;
		$lifetime = 604800;
		/*
		 * Set session cookie
		 */
		setcookie( 'sessionId', $sessionId, time() + $lifetime - 30, "/", $_SERVER['HTTP_HOST'] );
		/*
		 * Remember user name
		 */
		if ( $this->user != 'guest' )
		{
			setcookie( 'user', $this->user, time() + 60 * 60 * 24 * 365, "/", $_SERVER['HTTP_HOST'] );
		}
		/*
		 * Save the session
		 */
		$site = $this->site;
		$currentLocation = $_SERVER['REQUEST_URI'];
		$address = $this->address;
		$sql = "INSERT INTO
					`AccessControlSession`
				SET
					`sessionId` = '{$sessionId}',
					`user` = '{$user}',
					`site` = '{$site}',
					`currentLocation` = '{$currentLocation}',
					`remoteHost` = '{$address}',
					`lastActivity` = NOW()";
		TeamPlayers::$db->query( $sql );
	}
	/**
	 * Deletes the the current session or a specified session from the database
	 *
	 * @param		string $sessionId
	 * @return		boolean				True on success, false on failure or if session did not exist
	 * @access		protected
	 */
	protected function removeSession( $sessionId = "" )
	{
		if ( empty( $sessionId ) )
		{
			$sessionId = $this->sessionId;
		}
		$sql = "DELETE FROM `AccessControlSession` WHERE `sessionId` = '{$sessionId}'";
		TeamPlayers::$db->query( $sql );
	}
	/**
	 * Deletes expired sessions and optimizes the table
	 *
	 * @return		void
	 * @access		protected
	 */
	protected function removeExpiredSessions()
	{
		$lifetime = 604800;
		$sql = "DELETE FROM `AccessControlSession` WHERE `lastActivity` < NOW() - INTERVAL {$lifetime} SECOND";
		TeamPlayers::$db->query( $sql );
		$sql = "OPTIMIZE TABLE `AccessControlSession`";
		TeamPlayers::$db->query( $sql );
	}
	/**
	 * Fetches the current user's privileges
	 *
	 * @param		boolean		$force	Whether to force fetching of privileges
	 * @return		void
	 * @access		protected
	 */
	protected function fetchPrivileges( $force = false )
	{
		if ( $this->didFetchPrivileges == true && $force == false )
		{
			return;
		}
		/*
		 * Fetch privileges
		 */
		$this->privilege = $this->getPrivilegesForUser( $this->user, $this->roles );
		$this->didFetchPrivileges = true;
	}
	/**
	 * Returns an array containing user info (name and email address) for the specified user name
	 *
	 * @param		string		$user  User name
	 * @return		mixed       Array on success or boolean false on failure
	 * @access		public
	 * @todo 		add suport for LDAP resolve if user is not in database
	 */
	public function getUserInfo( $user )
	{
	    $user = TeamPlayers::$db->real_escape_string( $user );
		$sql = "SELECT `name`, `email`, `ldapUser`, `status` FROM `AccessControlUser` WHERE `user` = '{$user}'";
		if ( $result = TeamPlayers::$db->query( $sql ) )
		{
		    $info = $result->fetch_assoc();
		    $info['username'] = $user;
		    return $info;
		}
		return false;
	}
	/**
	 * Returns the specified user's privileges
	 *
	 * @param		string		$user
	 * @param       & array     $roles  Reference to array to populate with the user's roles
	 * @return		array
	 * @access		public
	 */
	public function getPrivilegesForUser( $user = '', & $roles = array() )
	{
		
	    if ( empty( $user ) )
	    {
	        $user = $this->user;
	    }
	    $user = TeamPlayers::$db->real_escape_string( $user );
	    /*
	     * Determine which roles are assigned to this user
	     */
	    
	    $assigned_roles = array();
	    $assigned_roles_temp = TeamPlayers::$db->selectAssoc( "SELECT `role`, `grant` FROM `AccessControlRoleAssignment` WHERE `user` = '{$user}' ORDER BY `role` ASC" );
	    foreach ( $assigned_roles_temp as $assigned_role )
	    {
	    	
	        $assigned_roles[] = $assigned_role['role'];
	        $roles_[] = array(
	                'role' => $assigned_role['role'],
	                'grant' => $assigned_role['grant'],
	                'inherited' => false
	        );
	    }
	    $role_inheritance = TeamPlayers::$db->selectAssoc( "SELECT `role`, `inherits`, `grant` FROM `AccessControlRoleInheritance` ORDER BY `inherits` ASC" );
	    foreach ( $role_inheritance as $inherited_role )
	    {
	        $grant = false;
	        $inherited = true;
	        /*
	         * Set the inherited flag to false if the role has also been assigned directly
	         */
	        if ( in_array( $inherited_role['inherits'], $assigned_roles ) )
	        {
	            $inherited = false;
	        }
	        /*
	         * Make sure a grant flag set to true is preserved if the role is inherited multiple times
	         */
	        if ( ! empty( $roles_ ) )
	        {
    	        foreach ( $roles_ as $role_ )
    	        {
    	            if ( $inherited_role['inherits'] == $role_['role'] && $role_['grant'] == true )
    	            {
    	                $grant = true;
    	            }
    	        }
    	    }
	        /*
	         * Add the role to the roles array
	         */
    	    $roles_[] = array(
    	            'role' => $inherited_role['inherits'],
    	            'grant' => $inherited_role['grant'] || $grant,
    	            'inherited' => $inherited
    	    );
	    }
	    $role_inheritance_temp = $role_inheritance;
	    $roles = array();
	    $roles_temp = $assigned_roles;
	    while ( list( , $role ) = each( $roles_temp ) )
	    {
	        foreach ( $role_inheritance_temp as $key => $inheritance )
	        {
	            if ( $role == $inheritance['role'] )
	            {
	                $roles_temp[] = $inheritance['inherits'];
	                unset( $role_inheritance_temp[$key] );
	                reset( $roles_temp );
	                break;
	            }
	        }
	    }
	    /*
	     * Fetch privileges belonging to the user's roles
	     */
	    $roles = array_unique( $roles_temp );	 
	    $roles_flat = $roles;   
	    $rolesString = "";
	    foreach ( $roles as $role )
	    {
	        $rolesString .= "'{$role}', ";
	    }
	    $rolesString = rtrim( $rolesString, ", " );
		$privileges = array();
		$sql = "SELECT
					`AccessControlPermissionAssignment`.`permission`, `class`, `object`, `grant`
				FROM
					`AccessControlPermissionAssignment`
				WHERE (
					`AccessControlPermissionAssignment`.`assignee`
				IN (
				    {$rolesString}
				) OR `AccessControlPermissionAssignment`.`assignee` = '{$user}' )";
		if ( $result = TeamPlayers::$db->selectAssoc( $sql ) )
		{
			foreach ( $result as $row )
			{
			    if ( ! empty( $row['object'] ) )
			    {
				    $privileges[$row['class']]['objects'][$row['object']][$row['permission']] = $row['permission'];
				    if ( $row['grant'] )
				    {
				        $privileges[$row['class']]['objects'][$row['object']]['grant'][$row['permission']] = $row['permission'];
				    }
				}
				else
				{
				    $privileges[$row['class']]['class'][$row['permission']] = $row['permission'];
				    if ( $row['grant'] )
				    {
				        $privileges[$row['class']]['class']['grant'][$row['permission']] = $row['permission'];
				    }
				}
			}
		}
		/*
		 * Fetch role descriptions
		 */
		$rolesAssoc = array();
		foreach ( $roles_ as $role_ )
		{
		    $rolesAssoc[$role_['role']] = $role_;
		}
		$rolesString = "";
		foreach ( $rolesAssoc as $role )
		{
		    $rolesString .= "'{$role['role']}', ";
		}
		$rolesString = rtrim( $rolesString, ", " );
		$sql = "SELECT
		            `role`,
		            `description`
		        FROM
		            `AccessControlRole`
		        WHERE
		            `role`
		        IN (
		            {$rolesString}
		        )";
		$descriptions = TeamPlayers::$db->selectAssoc( $sql );
		foreach ( $descriptions as $description )
		{
		    if ( isset( $rolesAssoc[$description['role']] ) )
		    {
		        $rolesAssoc[$description['role']]['description'] = $description['description'];
		    }
		}
		unset( $role );
		$roles = array();
		sort( $roles_flat );
		foreach ( $roles_flat as $role )
		{
		    $roles[] = $rolesAssoc[$role];
		}
		return $privileges;
	}
	/**
	 * Renews the specified session if still valid
	 *
	 * @param		string $sessionId
	 * @return		void
	 * @access		protected
	 */
	protected function renew( $sessionId )
	{
		if ( empty( $sessionId ) )
		{
			return;
		}
		$address = $this->address;
		$site = $this->site;
		$currentLocation = $_SERVER['REQUEST_URI'];
		$lifetime = 604800;
		$sql = "SELECT
					`name`, `user`, `email`, `password`, `status`
				FROM
					`AccessControlUser`
				WHERE
					`user` = (
				SELECT
					`user`
				FROM
					`AccessControlSession`
				WHERE (
					`sessionId` = '{$sessionId}'
				AND
					`lastActivity` < NOW() + INTERVAL {$lifetime} SECOND
				) )";
		/*
		 * Execute database query to authenticate user
		 */
		if ( $result = TeamPlayers::$db->selectAssoc( $sql ) )
		{
			$row = @$result[0];
			if ( ! empty( $row ) )
			{
			    $this->user = $row['user'];
				$this->name = $row['name'];
				$this->email = $row['email'];
				$this->password = $row['password'];
				$this->status = $row['status'];
				
				if ( $this->user )
				{
					/*
					 * Authentication successful
					 */
					$this->sessionId = $sessionId;
		//			TeamPlayers::$settings->fetchSettings();
					if ( $this->user != 'guest' )
					{
						$this->authenticated = true;
					}
				}
				else
				{
					/*
					 * Authentication failed
					 */
					$this->authenticate();
					return;
				}
			}
			else
			{
				/*
				 * Authentication failed
				 */
				$this->authenticate();
				return;
			}
		}
		/*
		 * Update last activity timestamp and current location
		 */
		$currentLocation = TeamPlayers::$db->real_escape_string( $currentLocation );
		$sql = "UPDATE
					`AccessControlSession`
				SET
					`lastActivity` = NOW(),
					`currentLocation` = '{$currentLocation}',
					`site` = '{$site}'
				WHERE
					`sessionId` = '{$sessionId}'"; 
		TeamPlayers::$db->query( $sql );
	}
	/**
	 * Sets the authenticationSuccessful property and writes to the authentication log
	 *
	 * @return		void
	 * @access		protected
	 */
	protected function authenticationSuccessful( $user )
	{
		$this->authenticationSuccessful = true;
		$this->writeToAuthenticationLog( $user, true );
	}
	/**
	 * Sets the authenticationFailed property, issues a message and writes to the authentication log
	 *
	 * @return		void
	 * @access		protected
	 */
	protected function authenticationFailed( $user, $password )
	{
		$this->authenticationFailed = true;
	//	TeamPlayers::$message->enter( COMessageTypeWarning, "Login failed. The user address and/or the password is incorrect.", '502986598123' );
		$this->writeToAuthenticationLog( $user, false );
	}
	/**
	 * Logs the authentication attempt
	 *
	 * @param		string $user
	 * @param		string $password
	 * @param		bool $successful
	 * @return		void
	 * @access		protected
	 */
	protected function writeToAuthenticationLog( $user, $successful )
	{
		if ( $user == 'guest' )
		{
			return;
		}
		$successful ? $successful = 1 : $successful = 0;
		$remoteAddress	= $_SERVER['REMOTE_ADDR'];
		$httpHost		= $_SERVER['HTTP_HOST'];
		$serverPort		= $_SERVER['SERVER_PORT'];
		$sql = "INSERT INTO `AccessControlAuthenticationLog` SET
					`user`			= '{$user}',
					`successful`	=  {$successful},
					`remoteAddress` = '{$remoteAddress}',
					`httpHost`		= '{$httpHost}',
					`serverPort`	=  {$serverPort}";
		TeamPlayers::$db->query( $sql );
	}
	/**
	* Gets the current session id from a cookie
	*
	* @return		string
	* @access		public
	*/
	public function sessionIdFromCookie()
	{
		$sessionId = "";
		if ( isset( $_COOKIE['sessionId'] ) )
		{
			if ( is_array( $_COOKIE['sessionId'] ) )
			{
				$sessionId = $_COOKIE['sessionId'][0];
			}
			else if ( is_string( $_COOKIE['sessionId'] ) )
			{
				$sessionId = $_COOKIE['sessionId'];
			}
		}
		return $sessionId;
	}
	/**
	 * Attempts binding to LDAP directory for authentication
	 *
	 * @param		string $user
	 * @param		string $password
	 * @return		mixed  Array on success or boolean false on failure
	 * @access		protected
	 */
	protected function ldapBind( $user, $password )
	{
	    if ( ! $connection = ldap_connect( "ldaps://at.ntnu.no" ) )
	    {
	        /*
	         * Connection failed
	         */
	    	
	        return false;
	        
	    }
	    ldap_set_option( $connection, LDAP_OPT_PROTOCOL_VERSION, 3 );
	    ldap_set_option( $connection, LDAP_OPT_REFERRALS, 0 );
	    /*
	     * Bind to LDAP directory using the provided credentials
	     */
	    $dn = "uid={$user}, ou=people, dc=ntnu, dc=no";
	    if ( ! $ldapbind = @ldap_bind( $connection, $dn, $password ) )
	    {
	        /*
	         * Bind failed
	         */
	        return false;
	    }
	    /*
	     * Fetch name and email address
	     */
	    if ( $sr = ldap_read( $connection, $dn, "objectClass=*" ) )
	    {
	    	if ( $entry = ldap_first_entry( $connection, $sr ) )
	    	{
	    		$name = @ ldap_get_values( $connection, $entry, "cn" );
	    		$email = @ ldap_get_values( $connection, $entry, "mail" );
	    	}
	    	ldap_free_result( $sr );
	    }
	    ldap_unbind( $connection );
	    /*
	     * Decode fetched data
	     */
	    $result = array();
	    $result['user'] = $user;
	    $result['password'] = $password;
	    if ( is_array( $name ) )
	    {
	        $result['name'] = self::utf8dec( $name[0] );
	    }
	    if ( is_array( $email ) )
	    {
            $result['email'] = self::utf8dec( $email[0] );
	    }
	    return $result;
	}
	
	/**
	 * 
	 * Searches the LDAP directory for a partial name
	 * @param 		string $name
	 * @param 		bool $ntnu
	 * @author		Martin Sommervold
	 */
	public function ldapSearch($name, $ntnu = false){
		if(strlen($name) < 4){
			return false;
		}
		$connection = ldap_connect( "ldaps://at.ntnu.no" );
		
		$dn = "ou=people, dc=ntnu, dc=no";
		if($ntnu){
			$filter = "cn=$name*";
		} else { //Search only for users associated with EPT
			$filter = "(&(cn=$name*)(noreduorgacronym=IVT-EPT))";
		}
		
		$justthese = array("cn", "sn", "mail");
		
		$sr=ldap_search($connection, $dn, $filter);
		
		$info = ldap_get_entries($connection, $sr);
		$hits = array();
		for($i = 0; $i < count($info)-1; $i++){
			$hits[$i]['name'] = $info[$i]['cn'][0];
			if(!empty($info[$i]['mail'][0])){
				$hits[$i]['mail'] = $info[$i]['mail'][0];
			} else {
				$hits[$i]['mail'] = $info[$i]['edupersonprincipalname'][0];
			}
			$hits[$i]['username'] = $info[$i]['uid'][0];
		}
		return $hits;
	}
	
	/**
	 * Creates a new user
	 *
	 * @param		string $user
	 * @param		string $email
	 * @param		string $password
	 * @param		string $name
	 * @param       string $phone
	 * @param       string $status
	 * @return		bool
	 * @access		public
	 */
	public function createUser( $user, $email, $password, $name, $phone, $status = 'pending' )
	{
        if ( ! $this->userExists( $user, $email ) )
        {
            $user        = TeamPlayers::$db->real_escape_string( $user );
            $email       = TeamPlayers::$db->real_escape_string( $email );
            $password    = sha1( $password );
            $name        = TeamPlayers::$db->real_escape_string( $name );
            $phone       = TeamPlayers::$db->real_escape_string( $phone );
            $status      = TeamPlayers::$db->real_escape_string( $status );
            $sql = "INSERT INTO
                        `AccessControlUser`
                    SET
                        `user` = '{$user}',
                        `email` = '{$email}',
                        `name` = '{$name}',
                        `phone` = '{$phone}',
                        `password` = '{$password}',
                        `status` = '{$status}',
                        `created` = NOW(),
                        `changed` = NOW()";
            return TeamPlayers::$db->query( $sql ) ? true : false;
        }
        return false;
	}
	/**
	 * Creates a new role
	 *
	 * @param		string $role  The role Id (CamelCase, no spaces)
	 * @param		string $description
	 * @param       string $grantor  The user to get the initial privilege to grant this role
	 * @return		bool
	 * @access		public
	 */
	public function createRole( $role, $description, $grantor = "" )
	{
	    if ( ! $this->allows( 'editRoles' ) )
	    {
	        return false;
	    }
	    if ( empty( $role ) || empty( $description ) )
	    {
	        return false;
	    }
	    $role = TeamPlayers::$db->real_escape_string( $role );
	    $description = TeamPlayers::$db->real_escape_string( $description );
	    if ( empty( $grantor ) )
	    {
	        $grantor = $this->user;
	    }
	    else
	    {
	        $grantor = TeamPlayers::$db->real_escape_string( $grantor );
	    }
	    $sql = "SELECT
	                `role`
	            FROM
	                `AccessControlRole`
	            WHERE
	                `role` = '{$role}'";
	    $result = TeamPlayers::$db->selectAssoc( $sql );
	    if ( ! empty( $result ) )
	    {
	        /*
	         * Role already exists
	         */
	        return false;
	    }
	    /*
	     * Create the role record
	     */
	    $sql = "INSERT INTO
	                `AccessControlRole`
	            SET
	                `role` = '{$role}',
	                `description` = '{$description}'";
	    if ( ! TeamPlayers::$db->query( $sql ) )
	    {
	        return false;
	    }
	    /*
	     * Create the initial role assignment
	     */
	    $this->assignRoleToUser( $role, $grantor, true, true );
	    return true;
	}
	/**
	 * Creates a new permission descriptor (permission Id / description pair)
	 *
	 * @param		string $permission  The role Id (CamelCase, no spaces)
	 * @param		string $description
	 * @return		bool
	 * @access		public
	 */
	public function createPermissionDescriptor( $permission, $description )
	{
	    if ( ! $this->allows( 'editPermissions' ) )
	    {
	        return false;
	    }
	    if ( empty( $permission ) || empty( $description ) )
	    {
	        return false;
	    }
	    $permission = TeamPlayers::$db->real_escape_string( $permission );
	    $description = TeamPlayers::$db->real_escape_string( $description );
	    $sql = "SELECT
	                `permission`
	            FROM
	                `AccessControlPermission`
	            WHERE
	                `permission` = '{$permission}'";
	    $result = TeamPlayers::$db->selectAssoc( $sql );
	    if ( ! empty( $result ) )
	    {
	        /*
	         * Permission already exists
	         */
	        return false;
	    }
	    /*
	     * Create the permission record
	     */
	    $sql = "INSERT INTO
	                `AccessControlPermission`
	            SET
	                `permission` = '{$permission}',
	                `description` = '{$description}'";
	    if ( ! TeamPlayers::$db->query( $sql ) )
	    {
	        return false;
	    }
	    return true;
	}
	/**
	 * Activates the specified user if it is currently pending approval
	 *
	 * @param		string $user
	 * @return		bool
	 * @access		public
	 */
	public function activateUser( $user )
	{
        $user = TeamPlayers::$db->real_escape_string( $user );
        $sql = "SELECT `status` FROM `AccessControlUser` WHERE `user` = '{$user}'";
        if ( $status = TeamPlayers::$db->fetchVariable( $sql ) && $status == 'pending' )
        {
            $this->setUserStatus( $user, 'active' );
        }
	}
	/**
	 * Sets account status for the specified user
	 *
	 * @param		string $user
	 * @param       string $status ('pending', 'active', 'disabled' or 'deleted')
	 * @return		bool False if the user doesn't exist
	 * @access		public
	 */
	public function setUserStatus( $user, $status )
	{
	    if ( $this->userExists( $user ) )
	    {
	        $user        = TeamPlayers::$db->real_escape_string( $user );
	        $status      = TeamPlayers::$db->real_escape_string( $status );
	        $sql = "UPDATE
	                    `AccessControlUser`
	                SET
	                    `status` = '{$status}',
	                    `changed` = NOW()
	                WHERE
	                    `user` = '{$user}'";
	        TeamPlayers::$db->query( $sql );
	        /*
	         * Invalidate active sessions if the user is being disabled or deleted
	         */
	        if ( $status == 'disabled' || $status == 'deleted' )
	        {
	            $sql = "DELETE FROM
	                        `AccessControlSession`
	                    WHERE
	                        `user` = '{$user}'";
	            TeamPlayers::$db->query( $sql );
	        }
	        return true;
	    }
	    return false;
	}
	/**
	 * Sets a property for the specified user
	 *
	 * @param		string $user
	 * @param       string $property
	 * @param       string $value
	 * @return		bool False if the user or specified property doesn't exist
	 * @access		public
	 */
	public function setUserProperty( $user, $property, $value )
	{
	    if ( $this->userExists( $user ) )
	    {
	        if ( ! in_array( $property, array( 'email', 'name', 'phone', 'password' ) ) )
	        {
	            return false;
	        }
	        if ( $property == 'password' )
	        {
	            $value = sha1( $value );
	        }
	        $property    = TeamPlayers::$db->real_escape_string( $property );
	        $value       = TeamPlayers::$db->real_escape_string( $value );
	        $sql = "UPDATE
	                    `AccessControlUser`
	                SET
	                    `{$property}` = '{$value}',
	                    `changed` = NOW()
	                WHERE
	                    `user` = '{$user}'";
	        return TeamPlayers::$db->query( $sql ) ? true : false;
	    }
	    return false;
	}
	/**
	 * Checks if the specified user exists
	 *
	 * @param		string $user
	 * @param		string $email
	 * @return		bool
	 * @access		public
	 */
	public function userExists( $user = "", $email = "" )
	{
		$user        = TeamPlayers::$db->real_escape_string( $user );
		$email       = TeamPlayers::$db->real_escape_string( $email );
	    $sql = "SELECT
	                *
	            FROM
	                `AccessControlUser`
	            WHERE
	                ( `user` = '{$user}' OR `email` = '{$email}' )";
	    if ( $result = TeamPlayers::$db->query( $sql ) )
	    {
	        if ( $result->num_rows != 0 )
	        {
	            return true;
	        }
	    }
	    return false;
	}
	/**
	 * Creates or edits a role
	 *
	 * @param		string $role
	 * @param		string $description
	 * @return		bool
	 * @access		public
	 */
	public function setRole( $role, $description )
	{
	    if ( ! $this->allows( 'editRoles' ) )
	    {
	        return false;
	    }
	    $role = TeamPlayers::$db->real_escape_string( $role );
	    $description = TeamPlayers::$db->real_escape_string( $description );
	    $sql = "REPLACE INTO
	                `AccessControlRole`
	            SET
	                `role` = '{$role}',
	                `description` = '{$description}'
	            ";
	    return TeamPlayers::$db->query( $sql ) ? true : false;
	}
	/**
	 * Deletes a role
	 *
	 * @param		string $role
	 * @param       bool $force  Forces deletion even though the role has assignments (causes assignments to be deleted as well)
	 * @param       bool $overridePermissions  Deletes the role even though the logged in user does not have the privilege to edit roles
	 * @return		bool
	 * @access		public
	 */
	public function deleteRole( $role, $force = false )
	{
	    if ( ! $this->allows( 'editRoles' ) && ! $overridePermissions )
	    {
	        return false;
	    }
	    $role = TeamPlayers::$db->real_escape_string( $role );
	    if ( $force )
	    {
	        $sql = "DELETE FROM
	                    `AccessControlRoleAssignment`
	                WHERE
	                    `role` = '{$role}'";
	        TeamPlayers::$db->query( $sql );
	    }
	    else
	    {
	        $sql = "SELECT
	                    `role`
	                FROM
	                    `AccessControlRoleAssignment`
	                WHERE
	                    `role` = '{$role}'";
	        $result = TeamPlayers::$db->selectAssoc( $sql );
	        if ( ! empty( $result ) )
	        {
	            /*
	             * This role has assignments and cannot be deleted
	             */
	            return false;
	        }
	    }
	    $sql = "DELETE FROM
	                `AccessControlRole`
	            WHERE
	                `role` = '{$role}'
	            ";
	    return TeamPlayers::$db->query( $sql ) ? true : false;
	}
	/**
	 * Creates or edits a permission
	 *
	 * @param		string $permission
	 * @param		string $description
	 * @return		bool
	 * @access		public
	 */
	public function setPermission( $permission, $description )
	{
	    $permission = TeamPlayers::$db->real_escape_string( $permission );
	    $description = TeamPlayers::$db->real_escape_string( $description );
	    $sql = "REPLACE INTO
	                `AccessControlPermission`
	            SET
	                `permission` = '{$permission}',
	                `description` = '{$description}'
	            ";
	    return TeamPlayers::$db->query( $sql ) ? true : false;
	}
	/**
	 * Deletes a permission
	 *
	 * @param		string $permission
	 * @param       bool $force  Forces deletion even though the permission has assignments (causes assignments to be deleted as well)
	 * @param       bool $overridePermissions  Deletes the permission even though the logged in user does not have the privilege to edit permissions
	 * @return		bool
	 * @access		public
	 */
	public function deletePermission( $permission, $force = false, $overridePermissions = false )
	{
	    if ( ! $this->allows( 'editPermissions' ) && ! $overridePermissions )
	    {
	        return false;
	    }
	    $permission = TeamPlayers::$db->real_escape_string( $permission );
	    if ( $force )
	    {
	        $sql = "DELETE FROM
	                    `AccessControlPermissionAssignment`
	                WHERE
	                    `permission` = '{$permission}'";
	        TeamPlayers::$db->query( $sql );
	    }
	    else
	    {
    	    $sql = "SELECT
    	                `permission`
    	            FROM
    	                `AccessControlPermissionAssignment`
    	            WHERE
    	                `permission` = '{$permission}'";
    	    $result = TeamPlayers::$db->selectAssoc( $sql );
    	    if ( ! empty( $result ) )
    	    {
    	        /*
    	         * This permission has assignments and cannot be deleted
    	         */
    	        return false;
    	    }
    	}
	    $sql = "DELETE FROM
	                `AccessControlPermission`
	            WHERE
	                `permission` = '{$permission}'
	            ";
	    return TeamPlayers::$db->query( $sql ) ? true : false;
	}
	/**
	 * Grants a privilege to a role
	 *
	 * @param		string $permission
	 * @param		string $role
	 * @param       string $class  Class name including namespace (e.g. TeamPlayers\AccessControl)
	 * @param       mixed $object  Object or Object UUID (string) (for object specific permissions)
	 * @param       bool $grant  Whether to grant the permission with grant privilege
	 * @param       bool $override  Whether to override grant permissions
	 * @param       bool
	 * @return		bool
	 * @access		public
	 */
	public function grantPermissionToRole( $permission, $role, $class, $object = "", $grant = false, $override = false )
	{
	    if ( ! $this->can( $permission, $class, $object, '', true ) && ! $override )
	    {
	        return false;
	    }
	    if ( is_object( $object ) )
	    {
	        if ( method_exists( $object, 'getUuid' ) )
	        {
	            $object = $object->getUuid();
	        }
	        else
	        {
	            return false;
	        }
	    }
	    $permission = TeamPlayers::$db->real_escape_string( $permission );
		$role = TeamPlayers::$db->real_escape_string( $role );
		$class = TeamPlayers::$db->real_escape_string( $class );
		$object = TeamPlayers::$db->real_escape_string( $object );
		$grant = $grant ? true : false;
		$sql = "REPLACE INTO
					`AccessControlPermissionAssignment`
				SET
					`permission`	= '{$permission}',
					`assignee`	    = '{$role}',
					`type`          = 'role',
					`class`         = '{$class}',
					`object`        = '{$object}',
					`grant`			= '{$grant}'
				";
		$result = TeamPlayers::$db->query( $sql ) ? true : false;
		$this->fetchPrivileges( true );
		return $result;
	}
	/**
	 * Grants a privilege to a user
	 *
	 * @param		string $permission
	 * @param		string $user
	 * @param       string $class  Class name including namespace (e.g. TeamPlayers\AccessControl)
	 * @param       mixed $object  Object or Object UUID (string) (for object specific permissions)
	 * @param       bool  Whether to grant the permission with grant privilege
	 * @param       bool $override  Whether to override grant permissions
	 * @return		bool
	 * @access		public
	 */
	public function grantPermissionToUser( $permission, $user, $class, $object = "", $grant = false, $override = false )
	{
	    if ( ! $this->can( $permission, $class, $object, '', true ) && ! $override )
	    {
	        return false;
	    }
	    if ( is_object( $object ) )
	    {
	        if ( method_exists( $object, 'getUuid' ) )
	        {
	            $object = $object->getUuid();
	        }
	        else
	        {
	            return false;
	        }
	    }
	    $permission = TeamPlayers::$db->real_escape_string( $permission );
		$user = TeamPlayers::$db->real_escape_string( $user );
		$class = TeamPlayers::$db->real_escape_string( $class );
		$object = TeamPlayers::$db->real_escape_string( $object );
		$grant = $grant ? true : false;
		$sql = "REPLACE INTO
					`AccessControlPermissionAssignment`
				SET
					`permission`	= '{$permission}',
					`assignee`	    = '{$user}',
					`type`          = 'user',
					`class`         = '{$class}',
					`object`        = '{$object}',
					`grant`			= '{$grant}'
				";
		$result = TeamPlayers::$db->query( $sql ) ? true : false;
		$this->fetchPrivileges( true );
		return $result;
	}
	/**
	 * Revokes a permission from a role or user
	 *
	 * @param		string $permission
	 * @param		string $assignee  Role or user name
	 * @param       string $class  Class name including namespace (e.g. TeamPlayers\AccessControl)
	 * @param		string $object  Object UUID (for object specific permissions)
	 * @return		bool
	 * @access		public
	 */
	public function revokePermission( $permission, $assignee, $class, $object = "" )
	{
		$permission = TeamPlayers::$db->real_escape_string( $permission );
		$assignee = TeamPlayers::$db->real_escape_string( $assignee );
		$class = TeamPlayers::$db->real_escape_string( $class );
		$object = TeamPlayers::$db->real_escape_string( $object );
		$sql = "DELETE FROM
					`AccessControlPermissionAssignment`
			    WHERE
					`permission`	= '{$permission}'
				AND
					`assignee`	    = '{$assignee}'
				AND
				    `class`         = '{$class}'";
		if ( ! empty( $object ) )
		{
		    $sql .= " AND `object` = '{$object}'";
		}
		$result = TeamPlayers::$db->query( $sql ) ? true : false;
		$this->fetchPrivileges( true );
		return $result;
	}
	/**
	 * Assigns a role to a user
	 *
	 * @param		string $role
	 * @param		string $user
	 * @param		string $site
	 * @param       bool $overrideGrantPrivilege
	 * @return		bool
	 * @access		public
	 */
	public function assignRoleToUser( $role, $user, $grant = false, $overrideGrantPrivilege = false )
	{
	    if ( ! $this->canAssignRole( $role ) && ! $overrideGrantPrivilege )
	    {
	        return false;
	    }
		$role = TeamPlayers::$db->real_escape_string( $role );
		$array = TeamPlayers::$db->selectAssoc( "SELECT `role` FROM `AccessControlRole` WHERE `role` = '{$role}'" );
		if ( empty( $array ) )
		{
		    /*
		     * Role doesn't exist
		     */
		    return false;
		}
		$user = TeamPlayers::$db->real_escape_string( $user );
		$grant = $grant ? true : false;
		$sql = "REPLACE INTO
					`AccessControlRoleAssignment`
				SET
					`role`	= '{$role}',
					`user`	= '{$user}',
					`grant` = '{$grant}'
				";
		$result = TeamPlayers::$db->query( $sql ) ? true : false;
		$this->fetchPrivileges( true );
		return $result;
	}
	/**
	 * Unassigns a role from a user
	 *
	 * @param		string $role
	 * @param		string $user
	 * @return		bool
	 * @access		public
	 */
	public function unassignRoleFromUser( $role, $user )
	{
	    if ( ! $this->canAssignRole( $role ) )
	    {
	        return false;
	    }
		$role = TeamPlayers::$db->real_escape_string( $role );
		$user = TeamPlayers::$db->real_escape_string( $user );
		$sql = "DELETE FROM 
					`AccessControlRoleAssignment` 
				WHERE 
					`user` = '{$user}'
				AND 
					`role`  = '{$role}'
				";
		$result = TeamPlayers::$db->query( $sql ) ? true : false;
		$this->fetchPrivileges( true );
		return $result;
	}
	/**
	 * Sets a permission inheritance relationship between two roles
	 *
	 * @param		string $role  The role inheriting permissions from another
	 * @param		string $inherits  The role whose permissions are being inherited
	 * @param       string $grant  Whether the inheriting role should have the permission to grant the inherited role to others
	 * @return		bool
	 * @access		public
	 */
	public function setRoleInheritance( $role, $inherits, $grant = false )
	{
	    if ( ! $this->allows( 'editRoleRelations' ) )
	    {
	        return false;
	    }
		$role = TeamPlayers::$db->real_escape_string( $role );
		$inherits = TeamPlayers::$db->real_escape_string( $inherits );
		$grant = $grant ? true : false;
		$sql = "REPLACE INTO
					`AccessControlRoleInheritance` 
				SET
				    `role` = '{$role}',
				    `inherits` = '{$inherits}',
				    `grant` = '{$grant}'
				";
		$result = TeamPlayers::$db->query( $sql ) ? true : false;
		$this->fetchPrivileges( true );
		return $result;
	}
	/**
	 * Unsets a permission inheritance relationship between two roles
	 *
	 * @param		string $role  The role inheriting permissions from another
	 * @param		string $inherits  The role whose permissions are being inherited
	 * @return		bool
	 * @access		public
	 */
	public function unsetRoleInheritance( $role, $inherits )
	{
	    if ( ! $this->allows( 'editRoleRelations' ) )
	    {
	        return false;
	    }
		$role = TeamPlayers::$db->real_escape_string( $role );
		$inherits = TeamPlayers::$db->real_escape_string( $inherits );
		$sql = "DELETE FROM
					`AccessControlRoleInheritance` 
				WHERE
				    `role` = '{$role}'
				AND
				    `inherits` = '{$inherits}'
				";
		$result = TeamPlayers::$db->query( $sql ) ? true : false;
		$this->fetchPrivileges( true );
		return $result;
	}
	/**
	 * Checks if Access Control allows the specified action by the current user, or another specified user
	 *
	 * @param       string $action
	 * @param       string $user
	 * @return		bool
	 * @access		public
	 */
	public function allows( $action, $user = "" )
	{
	    $class = get_class( $this );
		return $this->can( $action, $class, '', $user );
	}
	 /**
	  * Decodes UTF8 entitities from LDAP data
	  *
	  * @param      $s_String
	  * @return		string
	  * @access		public
	  */
	 public static function utf8dec( $s_String )
	 {
	     $s_String = html_entity_decode(htmlentities($s_String . " ", ENT_COMPAT, 'UTF-8'));
	     return substr($s_String, 0, strlen($s_String) - 1);
	 }
}
?>
